package com.online.pay.common.http;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.async.DeferredResult;

/**
 * {@code DeferredResultMiniCache}负责缓存Spring MVC中处理异步请求的{@code DeferredResult}。
 * <p>通过注解@Autowired可以注入实例对象。</p>
 * <p><strong>设计思路：</strong>
 * <p>http客户端向平台发送http请求时，平台通过springMVC产生DeferredResult响应对象，该组件将DeferredResult对象按特定标识存储到缓存中。在平台完成消息处理并需要像客户端响应处理结果时，从缓存中通过特定标识取出所需DeferredResult对象向客户端响应结果。</p>
 * 
 * <p><strong>主要方法如下：</strong></p>
 * <p>
 * 获取指定标识的DeferredResult，get(java.lang.String key)
 * </p>
 * <p>
 * 存储指定标识的DeferredResult，put(java.lang.String key, org.springframework.web.context.request.async.DeferredResult<java.lang.String> result)
 * </p>
 * 
 * @since xpay-common 0.0.1
 * @author Eshin
 * @date 2016.3.23
 */
@Configuration
@ConditionalOnWebApplication
public class DeferredResultMiniCache {

	/**
	 * 存放DeferredResult的Map对象
	 */
	private Map<String, DeferredResult<String>> resultMap;

	/**
	 * 默认构造函数
	 */
	public DeferredResultMiniCache() {
		// 默认缓存容量大小为2000
		this(2000);
	}

	/**
	 * @param timeoutSecond
	 *            - 指定超时时间，单位为秒
	 * @param capcity
	 *            - 指定缓存容量大小
	 */
	public DeferredResultMiniCache(int capcity) {
		// 构造数据结构
		this.resultMap = new ConcurrentHashMap<>(capcity);
		// 创建定时清理缓存线程
	}

	/**
	 * 将DeferredResult放入缓存
	 * 
	 * @param key
	 *            - 关键字
	 * @param result
	 *            - DeferredResult对象
	 */
	public void put(String key, DeferredResult<String> result) {
		result.onCompletion(new CompletionCallBack(key,this));
		this.resultMap.put(key, result);
	}


	/**
	 * 从缓存中获取key对应的对象，并将此key值删除
	 * 
	 * @param key
	 *            - 关键字
	 * @return
	 */
	public DeferredResult<String> get(String key) {
		DeferredResult<String> deferredResult = this.resultMap.remove(key);
		if(deferredResult == null){
			return null;
		}
		return deferredResult;
	}

	/**
	 * 停止函数
	 */
	public void destory() {
		this.resultMap.clear();
		this.resultMap=null;
	}


	public Map<String, DeferredResult<String>> getResultMap() {
		return this.resultMap;
	}

	/**
	 * deferredresult调用完成后回调，包含正常流程和超时异常流程
	 * @author Eshin
	 *
	 */
	private class CompletionCallBack implements Runnable {

		String key;
		
		DeferredResultMiniCache deferredResultMiniCache;
		
		
		public CompletionCallBack(String key, DeferredResultMiniCache deferredResultMiniCache) {
			this.key = key;
			this.deferredResultMiniCache = deferredResultMiniCache;
		}

		@Override
		public void run() {
			
			DeferredResult<String> deferredResult = deferredResultMiniCache.get(key);
			if (null != deferredResult ) {
				System.out.println(String.format("删除无效的deferredResult,Key为：%s", key));
			}
		}

	}

}
